﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;

namespace AppBrowser.Common
{
    /// <summary>
    /// Class to find out currently installed windows apps (via the registry key)
    /// </summary>
    public class InstalledApps
    {
        /// <summary>
        /// Store the most recent call to find out current programs list
        /// </summary>
        private static List<InstalledAppItem> InstalledAppList;
        
        // last datetime queried
        private static DateTime LastQueriedDate;

        /// <summary>
        /// Perform a query to get the list of currently installed applications
        /// </summary>
        public static void QueryInstalledApps()
        {
            Microsoft.Win32.RegistryKey regKey  = Microsoft.Win32.Registry.LocalMachine;
            Microsoft.Win32.RegistryKey subKey1 = regKey.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
            string[] subKeyNames = subKey1.GetSubKeyNames();
            InstalledAppList = new List<InstalledAppItem>();

            string[] DateFmts = new string[] { "yyyy/MM/dd hhmmss", "yyyyMMdd hhmmss" };

            foreach (string subKeyName in subKeyNames)
            {
                // Console.WriteLine(subKeyName + "\r\n");
                Microsoft.Win32.RegistryKey subKey2 = subKey1.OpenSubKey(subKeyName);

                if (ValueNameExists(subKey2.GetValueNames(), "DisplayName"))
                {
                    InstalledAppItem ia = new InstalledAppItem(subKey2.GetValue("DisplayName").ToString(), subKey2.GetValue("DisplayVersion","").ToString());

                    ia.HelpLink = subKey2.GetValue("HelpLink", "").ToString();

                    string DateVal = subKey2.GetValue("InstallDate", "20080101").ToString() + " 000000";
                    try
                    {
                        ia.InstallDate = DateTime.ParseExact(DateVal, DateFmts, null, DateTimeStyles.AdjustToUniversal);
                    }
                    catch
                    {
                        ia.InstallDate = DateTime.Now;
                    }

                    // TODO: optimize
                    string iconfile =subKey2.GetValue("DisplayIcon", "").ToString();
                    if (iconfile != "")
                    {
                        int icnidx = iconfile.LastIndexOf(',');
                        if (icnidx != -1)
                        {
                            iconfile = iconfile.Remove(icnidx);
                        }

                        // load icon from exe file
                        ia.DisplayIcon = IconExtract.ExtractIconFromFile(iconfile);
                    
                    }

                    ia.InstallLocation = subKey2.GetValue("InstallLocation", "").ToString();
                    ia.Publisher = subKey2.GetValue("Publisher", "").ToString();

                    InstalledAppList.Add(ia);
                }
                else
                {
                    Console.WriteLine("NOT EXIST: --- " + subKeyName + "\r\n");

                }

                subKey2.Close();
            }

            subKey1.Close();
            LastQueriedDate = DateTime.Now;
            // Console.WriteLine(DumpListToString());
            
        }

        public static string DumpListToString()
        {
            StringBuilder str = new StringBuilder();
            foreach (InstalledAppItem ia in InstalledAppList)
            {
                str.Append(ia.ToString() + "\r\n");
            }

            return str.ToString() + InstalledAppList.Count;

        }

        /// <summary>
        /// Get Applications with search term appname in it
        /// </summary>
        /// <param name="appname">name ie firefox, thunderbird</param>
        public static List<InstalledAppItem> FindInstalledApplication(string appname)
        {
            List<InstalledAppItem> listItems = new List<InstalledAppItem>();
            
            // TODO: replace this with .findall method
            foreach (InstalledAppItem ia in InstalledAppList)
            {
                if (ia.DisplayName.ToLower().Contains(appname.ToLower()))
                {
                    listItems.Add(ia);
                }
                
            }
            return listItems;
        }

        /// <summary>
        /// Compare application version (to determine current release is upto date)
        /// </summary>
        /// <param name="ver1"></param>
        /// <param name="ver2"></param>
        /// <returns></returns>
        public static bool CompareAppVersion(string ver1, string ver2)
        {
            Version v1 =new Version(ver1);
            Version v2 = new Version(ver2);

            if (v1<v2) {
                return true;
            } else {
                return false;
            }
        }

        private static bool ValueNameExists(string[] valueNames, string valueName)
        {
            foreach (string s in valueNames)
            {
                if (s.ToLower() == valueName.ToLower()) return true;
            }

            return false;
        }


        public class InstalledAppItem
        {
            public string DisplayName;
            private System.Drawing.Icon _displayIcon;
            public System.Drawing.Icon DisplayIcon
            {
                get { return _displayIcon; }
                set { _displayIcon = value; }
            }
            public string DisplayVersion;
            public DateTime InstallDate;
            public string InstallLocation;
            public string HelpLink;
            public string Publisher;

            public InstalledAppItem(string displayname, string displayversion)
            {
                DisplayName = displayname;
                DisplayVersion = displayversion;
            }

            public override string ToString()
            {
                return DisplayName + " (v" + DisplayVersion + ") Publisher: " + Publisher + " Install Date: " + InstallDate.ToShortDateString();
            }
        }
    }
}
